虚拟网卡导致 apollo 启动太慢的问题
项目中集成了 apollo 之后, 在本地启动项目速度很慢, 比没有集成 apollo 的时候慢了 30s~40s.
这里做了一个简单的例子, 主要是一个 SpringBoot 的启动类和一个 apollo 的配置类, 配置类很简单:
1 | @Configuration |
启动项目:
可以看到一个很简单的只是集成了 apollo 的项目启动就花费了 39s 左右.到底是什么导致的呢?
可以使用 jvisualvm
进行观察:
可以看到大部分的时间都消耗在了 NetworkInterfaceManager#findValidateIp()
方法上面:
1 | public InetAddress findValidateIp(List<InetAddress> addresses) { |
此方法要做的事情就是寻找有效的 IP, 另外可以看到此方法的 if (!Objects.equals(address.getHostName(), address.getHostAddress()))
片段也注释了 TODO fix performance issue when calling getHostName
.
不过 jvisualvm
并没有明确的指示出是 InetAddress#getHostName()
方法耗时而导致 findValidateIp()
方法的耗时.换成 jProfiler
再重新观察一下:
此时就可以很明确的看出是 InetAddress#getHostName()
耗时而导致的问题.
关于 InetAddress#getHostName()
执行慢的问题可搜索下相关的话题.先看看有什么办法可以先 解决这个问题.
到这里我们可以想到的是有什么办法可以规避此方法的调用, 看下此方法的调用处, 也就是 NetworkInterfaceManager#load()
方法.
1 | private void load() { |
从这里可以看到看出如果 getProperty("host.ip")
可以取到 ip 值, 那么 findValidateIp()
方法就不会被调用, 这样项目启动是不是就可以很快了? 在项目启动类加上 vm args: -Dhost.ip=IP地址
, 重新启动项目:
此时可以看到项目启动非常快.
现在再思考下, 虽然 InetAddress#getHostName()
执行耗时, 但是也不至于那么慢, 如果真的这样, 那么岂不是只要用了这个方法的项目启动都会很慢.
再回头看看 NetworkInterfaceManager#load()
方法:
1 | try { |
findValidateIp()
方法接收的是一个地址列表, 在本机调试, 在使用有线网的情况下 addresses
参数的个数是 10(无线网是 12).为什么会这么多, 因为本机安装了虚拟机, 多出了几块虚拟网卡, 查看网络连接:
此时可以想到是不是因为是虚拟网卡而导致的问题? 另外 NetworkInterfaceManager#load()
方法中有 ni.isUp()
的判断, 此方法会判断网卡是否启用并运行.将除了以太网和 WLAN 之外的网络都禁用, 此时再重新运行项目, 发现项目启动速度就很快了:
从这个例子中可以看到, 如果项目集成 apollo 之后在本地测试启动速度很慢, 那么可以看下本地是否安装了虚拟机, 或者可以通过传入 vm args -Dhost.ip=IP地址
的方式来解决项目启动慢的问题.
- 感谢您的阅读,本文由 ykgarfield 版权所有。如若转载,请注明出处:ykgarfield
- 文章链接: https://ykgarfield.github.io/2018/06/26/Java/性能/虚拟网卡导致 apollo 启动太慢的问题/